/**
 * On implementation of the IValidatingImageService interface using java.awt.*.
 * 
 * @author Dafei.Shi
 * @since May 29th, 2008 
 * Copyright 2008 Hilaver Ltd. All rights reserved.
 */

package com.hilaver.dzmis.service.impl;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;

import com.hilaver.dzmis.service.IValidatingImageService;

public class ValidatingImageServiceImpl implements IValidatingImageService {

	private String validatingCode;

	private Random random = new Random();

	private Graphics g;

	private BufferedImage image;

	public ValidatingImageServiceImpl() {
		this.random = new Random();
		this.image = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT,
				BufferedImage.TYPE_INT_RGB);
		this.g = image.getGraphics();
		this.setValidatingCode();
	}

	@Override
	public String getValidatingCode() {
		return this.validatingCode;
	}

	@Override
	public BufferedImage generateImage() {
		this.g.setColor(this.getRandColor(200, 250));
		this.g.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);

		this.g.setFont(new Font(FONT_TYPE, Font.PLAIN, FONT_SIZE));

		for (int i = 0; i < this.validatingCode.length(); i++) {
			char tmp = this.validatingCode.charAt(i);
			this.g.setColor(new Color(20 + random.nextInt(110), 20 + random
					.nextInt(110), 20 + random.nextInt(110)));
			this.g.drawString(String.valueOf(tmp), 13 * i + 6, 16);
		}
		this.drawLine();

		this.g.dispose();
		return this.image;
	}

	/**
	 * Draw LINE_COUNT lines on the validating image.
	 */
	private void drawLine() {
		g.setColor(this.getRandColor(160, 200));
		for (int i = 0; i < LINE_COUNT; i++) {
			int x1 = this.random.nextInt(IMAGE_WIDTH);
			int y1 = this.random.nextInt(IMAGE_HEIGHT);
			int dx = this.random.nextInt(LINE_MAX_LENGH);
			int dy = this.random.nextInt(LINE_MAX_LENGH);
			g.drawLine(x1, y1, x1 + dx, y1 + dy);
		}

	}

	/**
	 * Get random color according to the rA and rB
	 * 
	 * @param rA
	 * @param rB
	 * @return
	 */
	private Color getRandColor(int rA, int rB) {
		if (rA > rB) {
			int tmp = rA;
			rA = rB;
			rB = tmp;
		}
		if (rA > 255)
			rA = 255;
		if (rB > 255)
			rB = 255;
		int r = rA + this.random.nextInt(rB - rA);
		int g = rA + this.random.nextInt(rB - rA);
		int b = rA + this.random.nextInt(rB - rA);
		
		//r, g, b should be less than 255.
		if (r > 255)
			r = 255;
		if (g > 255)
			r = 255;
		if (b > 255)
			b = 255;
		return new Color(r, g, b);
	}

	/**
	 * Set the random code which is corresponding to the validating image.
	 */
	private void setValidatingCode() {
		this.validatingCode = "";
		for (int i = 0; i < RANDOM_CODE_LENGHT; i++) {
			int x = this.random.nextInt(C.length);
			String rand = String.valueOf(C[x]);
			this.validatingCode += rand;
		}
	}

	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			ValidatingImageServiceImpl viSI = new ValidatingImageServiceImpl();
			System.out.println(viSI.getValidatingCode());
			try {
				ImageIO.write(viSI.generateImage(), "JPEG", new File("d:/"
						+ new Random().nextLong() + ".jpg"));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
